package com.bdqn.wx.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;

@SuppressWarnings({ "rawtypes", "unchecked" })
public class BaseDao<T> implements IBaseDao<T> {

	private Class entityClass;

	public BaseDao() {
		entityClass = this.getEntityClass();
	}

	/**
	 * 使用反射获取当前泛型参数的数据类型
	 * 
	 * @return
	 */
	private Class getEntityClass() {
		try {
			ParameterizedType paramerType = (ParameterizedType) this.getClass()
					.getGenericSuperclass();
			return (Class) paramerType.getActualTypeArguments()[0];
		} catch (Exception e) {

		}
		return null;
	}

	private Map<String, Object> createPageData(List<T> data, int pageIndex,
			int pageSize, int total) {

		Map<String, Object> map = new HashMap<String, Object>();
		int pageTotal = (int) Math.ceil((double) total / pageSize);
		map.put("data", data);
		map.put("pageIndex", pageIndex);
		map.put("pageSize", pageSize);
		map.put("total", total);
		map.put("pageTotal", pageTotal);
		map.put("hasNext", pageIndex < pageTotal);
		map.put("hasPrev", pageIndex > 1);
		
		return map;
	}

	@Override
	public Session getSession() {
		return HibernateUtil.getSession();
	}

	@Override
	public void save(T record) {
		Session session = this.getSession();
		Transaction tx = session.beginTransaction();
		try {
			session.save(record);
		} catch (HibernateException e) {
			e.printStackTrace();
			tx.rollback();
		}
		tx.commit();
	}

	@Override
	public void delete(Serializable id) {
		this.getSession().delete(this.findById(id));

	}

	@Override
	public void delete(T record) {
		this.getSession().delete(record);

	}

	@Override
	public void update(T record) {
		this.getSession().update(record);
	}

	@Override
	public T findById(Serializable id) {
		return (T) this.getSession().get(entityClass, id);
	}

	@Override
	public List<T> find(String hql, Map<String, Object> params) {
		Query query = this.getSession().createQuery(hql);
		query.setProperties(params);
		return query.list();
	}

	@Override
	public Map<String, Object> find(String hql, int pageIndex, int pageSize,
			Map<String, Object> params) {

		String hqlCount;
		// 通过给定的HQL语句查询全部条数
		int i = hql.indexOf("from");
		if (i == 0) {
			hqlCount = "select count(*) " + hql;
		} else {
			hqlCount = "select count(*) " + hql.substring(i);
		}
		int total = Integer.parseInt(this.getSession().createQuery(hqlCount)
				.uniqueResult().toString());

		Query query = this.getSession().createQuery(hql);
		query.setProperties(params);

		query.setFirstResult((pageIndex - 1) * pageSize);
		query.setMaxResults(pageSize);

//		Map<String, Object> map = new HashMap<String, Object>();
//		int pageTotal = (int) Math.ceil((double) total / pageSize);
//		map.put("data", query.list());
//		map.put("pageIndex", pageIndex);
//		map.put("pageSize", pageSize);
//		map.put("total", total);
//		map.put("pageTotal", pageTotal);
//		map.put("hasNext", pageIndex < pageTotal);
//		map.put("hasPrev", pageIndex > 1);

		return this.createPageData(query.list(), pageIndex, pageSize, total);
	}

	@Override
	public Map<String, Object> find(int pageIndex, int pageSize) {
		Criteria criteria = this.getSession().createCriteria(entityClass);

		// 查询总数
		criteria.setProjection(Projections.rowCount());
		int total = Integer.parseInt(criteria.uniqueResult().toString());
		criteria.setProjection(null);
		criteria.setFirstResult((pageIndex - 1) * pageSize);
		criteria.setMaxResults(pageSize);


		return this.createPageData(criteria.list(), pageIndex, pageSize, total);
	}

	@Override
	public List<T> find(DetachedCriteria detachedCriteria) {
		return detachedCriteria.getExecutableCriteria(getSession()).list();
	}

	@Override
	public Map<String, Object> find(DetachedCriteria detachedCriteria,
			int pageIndex, int pageSize) {
		// 查询总数

		int total = Integer.parseInt(detachedCriteria
				.getExecutableCriteria(getSession())
				.setProjection(Projections.rowCount()).uniqueResult()
				.toString());
		// 分页操作
		Criteria criteria = detachedCriteria
				.getExecutableCriteria(getSession());
		criteria.setFirstResult((pageIndex - 1) * pageSize);
		criteria.setMaxResults(pageSize);
		
		return this.createPageData(criteria.list(), pageIndex, pageSize, total);
	}

}
